<template>
  <div class="particle-background">
    <canvas ref="canvasRef"></canvas>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'

const props = defineProps({
  config: {
    type: Object,
    default: () => ({
      count: 50,
      speed: 'medium',
      color: '#667eea',
      size: 'medium',
      twinkle: false,
      shape: 'circle'
    })
  }
})

const canvasRef = ref(null)
let ctx = null
let particles = []
let animationId = null

class Particle {
  constructor(canvas) {
    this.canvas = canvas
    this.reset()
    this.y = Math.random() * canvas.height
    this.opacity = Math.random()
  }

  reset() {
    this.x = Math.random() * this.canvas.width
    this.y = -10
    this.size = this.getSize()
    this.speedY = this.getSpeed()
    this.speedX = (Math.random() - 0.5) * 0.5
    this.opacity = Math.random()
    this.color = this.getColor()
  }

  getSize() {
    const sizeMap = {
      small: Math.random() * 2 + 1,
      medium: Math.random() * 4 + 2,
      large: Math.random() * 8 + 4
    }
    return sizeMap[props.config.size] || sizeMap.medium
  }

  getSpeed() {
    const speedMap = {
      slow: Math.random() * 0.5 + 0.2,
      medium: Math.random() * 1 + 0.5,
      fast: Math.random() * 2 + 1
    }
    return speedMap[props.config.speed] || speedMap.medium
  }

  getColor() {
    if (props.config.color === 'rainbow') {
      const colors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#f7b731', '#5f27cd', '#00d2d3']
      return colors[Math.floor(Math.random() * colors.length)]
    }
    return props.config.color
  }

  update() {
    this.y += this.speedY
    this.x += this.speedX

    if (this.y > this.canvas.height) {
      this.reset()
    }

    if (props.config.twinkle) {
      this.opacity += (Math.random() - 0.5) * 0.1
      this.opacity = Math.max(0.2, Math.min(1, this.opacity))
    }
  }

  draw(context) {
    context.save()
    context.globalAlpha = this.opacity
    context.fillStyle = this.color

    if (props.config.shape === 'bubble') {
      // 泡泡效果
      const gradient = context.createRadialGradient(
        this.x, this.y, 0,
        this.x, this.y, this.size
      )
      gradient.addColorStop(0, this.color)
      gradient.addColorStop(0.5, this.color + '80')
      gradient.addColorStop(1, this.color + '00')
      context.fillStyle = gradient
      context.beginPath()
      context.arc(this.x, this.y, this.size, 0, Math.PI * 2)
      context.fill()
    } else {
      // 普通圆形
      context.beginPath()
      context.arc(this.x, this.y, this.size, 0, Math.PI * 2)
      context.fill()
    }

    context.restore()
  }
}

const init = () => {
  const canvas = canvasRef.value
  if (!canvas) return

  canvas.width = canvas.offsetWidth
  canvas.height = canvas.offsetHeight
  ctx = canvas.getContext('2d')

  particles = []
  for (let i = 0; i < props.config.count; i++) {
    particles.push(new Particle(canvas))
  }
}

const animate = () => {
  if (!ctx || !canvasRef.value) return

  ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)

  particles.forEach(particle => {
    particle.update()
    particle.draw(ctx)
  })

  animationId = requestAnimationFrame(animate)
}

const handleResize = () => {
  init()
}

onMounted(() => {
  init()
  animate()
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  if (animationId) {
    cancelAnimationFrame(animationId)
  }
  window.removeEventListener('resize', handleResize)
})

watch(() => props.config, () => {
  init()
}, { deep: true })
</script>

<style scoped>
.particle-background {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: block;
}
</style>

